/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package CocoFood.utils;

import com.Ostermiller.util.Base64;
import java.security.*;
import java.util.Random;
import javax.crypto.*;
import javax.crypto.spec.*;

/**
 *
 * @author KF
 */
public final class DESedePasswordEncrypt {

    private final byte[] DESedeKeyBytes = {
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
        0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
        0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,};

    public DESedePasswordEncrypt(String saltKey, String characterEncoding) throws Exception {
        byte[] keyBytes = DESedeKeyBytes;
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        byte[] ivBytes = Base64.decodeToBytes(saltKey);
        IvParameterSpec iv = new IvParameterSpec(ivBytes);
        this.characterEncoding = characterEncoding;
        this.encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
        this.encryptCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, iv);
        this.decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
        this.decryptCipher.init(javax.crypto.Cipher.DECRYPT_MODE, key, iv);
    }

    public DESedePasswordEncrypt(String saltKey) throws Exception {
        byte[] keyBytes = DESedeKeyBytes;
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        byte[] ivBytes = Base64.decodeToBytes(saltKey);
        IvParameterSpec iv = new IvParameterSpec(ivBytes);
        this.characterEncoding = "ASCII";
        this.encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
        this.encryptCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, iv);
        this.decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
        this.decryptCipher.init(javax.crypto.Cipher.DECRYPT_MODE, key, iv);
    }

    public DESedePasswordEncrypt() throws Exception {
        byte[] keyBytes = DESedeKeyBytes;
        SecretKey key = new SecretKeySpec(keyBytes, "DESede");
        byte[] ivBytes = Base64.decodeToBytes("20220220220");
        IvParameterSpec iv = new IvParameterSpec(ivBytes);
        this.characterEncoding = "ASCII";//generic password encryption
        this.encryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
        this.encryptCipher.init(javax.crypto.Cipher.ENCRYPT_MODE, key, iv);
        this.decryptCipher = Cipher.getInstance("DESede/CBC/PKCS5Padding", "SunJCE");
        this.decryptCipher.init(javax.crypto.Cipher.DECRYPT_MODE, key, iv);
    }

    synchronized public String encrypt(String password) throws Exception {
        byte[] passwordBytes = password.getBytes(characterEncoding);
        byte[] encryptedPasswordBytes = this.encryptCipher.doFinal(passwordBytes);
        String encodedEncryptedPassword = Base64.encodeToString(encryptedPasswordBytes);
        return encodedEncryptedPassword;
    }

    synchronized public String decrypt(String encodedEncryptedPassword) throws Exception {
        byte[] encryptedPasswordBytes = Base64.decodeToBytes(encodedEncryptedPassword);
        byte[] passwordBytes = this.decryptCipher.doFinal(encryptedPasswordBytes);
        String recoveredPassword = new String(passwordBytes, characterEncoding);
        return recoveredPassword;
    }

    // Simple test 
    public static void main(String[] args) {
        try {
            // Make sure SUN JCE are a provider
            Security.addProvider(new com.sun.crypto.provider.SunJCE());

            // The DES EDE Key - any 24 bytes will do though beware of weak keys.
            // This could be read from a file.
            final byte[] DESedeKeyBytes = {
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
                0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
                0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,};


            // Password encrypt agent that assumes the password is only ASCII characters
            // Change character encoding as required.
            //DESedePasswordEncrypt passwordEncryptAgent = new DESedePasswordEncrypt(sandKey, "ASCII");
            DESedePasswordEncrypt passwordEncryptAgent = new DESedePasswordEncrypt();
            // Get the password to encrypt from the command line
            String password = (args.length == 0) ? "theLOve202" : args[0];

            // Since the example password encrypter is setup to convert the password to ASCII bytes
            // before encrypting, make sure that the password is in fact ASCII (in this case printable ASCII).
            if (!password.matches("[ -~]{6,}")) {
                throw new IllegalArgumentException("Password must be printable ASCII");
            }


            String encodedEncryptedPassword = passwordEncryptAgent.encrypt(password);


        } catch (Exception e) {
            e.printStackTrace(System.out);
        }
    }
    private String characterEncoding;
    private Cipher encryptCipher;
    private Cipher decryptCipher;

    public final String createRandomSalt() {
        byte[] salt = new byte[8];
        Random rand;
        for (int j = 0; j < 2; j++) {
            rand = new Random();
            int i = rand.nextInt();
            salt[0 + j * 4] = (byte) (i >> 24);
            salt[1 + j * 4] = (byte) (i >> 16);
            salt[2 + j * 4] = (byte) (i >> 8);
            salt[3 + j * 4] = (byte) i;
        }
        return Base64.encodeToString(salt);
    }
}
